//Heap_memory_management_helper.h
#ifndef HEAP_MEMORY_MANAGEMENT_HELPER_H
#define HEAP_MEMORY_MANAGEMENT_HELPER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>



//默认矩阵为int类型
typedef struct
{
    int **data;
    unsigned int rows;   //number of rows
    unsigned int cols;   //number of columns
} Matrix;

typedef struct
{
    float **data;
    unsigned int rows;
    unsigned int cols;
} Matrix_float;

typedef struct
{
    double **data;
    unsigned int rows;
    unsigned int cols;
} Matrix_double;


//Stores the created matrix
typedef struct
{
    Matrix **matrixs;
    unsigned int num;       //number of matrixs
    unsigned int max_num;   //max number of matrixs (first time is 16)

    Matrix_float **matrixs_float;
    unsigned int num_float;
    unsigned int max_num_float;

    Matrix_double **matrixs_double;
    unsigned int num_double;
    unsigned int max_num_double;

    unsigned int all_num;
} Manager;

//max_num_flaot and max_num_double is Half the number of max_num
#define MAX_NUM 16



#ifdef __cplusplus  /*If compile C++*/
/*Let C code be defined in C++*/

extern "C" {
#else
#define __MANAGEMENT_VLA
/*C++不支持变长数组*/
void copy_array_to_matrix(Matrix* m,unsigned int rows,unsigned int cols, int array[rows][cols]);
void copy_array_to_float_matrix(Matrix_float* mf,unsigned int rows,unsigned int cols, float array[rows][cols]);
void copy_array_to_double_matrix(Matrix_double* md,unsigned int rows,unsigned int cols, double array[rows][cols]);
#endif




/*
对二维数组的全生命周期管理
*/

Manager *manager_instance(void);     //The only instance returned is the manager instance
Matrix *create_matrix(unsigned int rows, unsigned int cols);
Matrix_float *create_float_matrix(unsigned int rows, unsigned int cols);
Matrix_double *create_double_matrix(unsigned int rows, unsigned int cols);



Matrix* matrix_multiply(Matrix* A, Matrix* B);
Matrix_double* matrix_multiply_double(Matrix_double* A, Matrix_double* B);

Matrix* matrix_add(Matrix* A, Matrix* B);
Matrix_double* matrix_add_double(Matrix_double* A, Matrix_double* B);

Matrix* matrix_sub(Matrix *A, Matrix* B);
Matrix_double* matrix_sub_double(Matrix_double* A, Matrix_double* B);

Matrix* matrix_cofactor(Matrix* A, int p, int q);
Matrix_double* matrix_cofactor_double(Matrix* A, int p, int q);

Matrix* matrix_adjoint(Matrix* A);
Matrix_double* matrix_adjoint_double(Matrix* A);

Matrix_double* matrix_inverse(Matrix *A);

double determinant(Matrix *A);
double determinant_double(Matrix_double* A);

void matrix_eigen(Matrix* A, double* eigenvalues, double* eigenvectors);
void set_matrix(Matrix* m, const char* str);

#ifndef __MANAGEMENT_VLA
void copy_array_to_matrix(Matrix* m,unsigned int rows,unsigned int cols, int **array);
void copy_array_to_float_matrix(Matrix_float* mf,unsigned int rows,unsigned int cols, float **array);
void copy_array_to_double_matrix(Matrix_double* md,unsigned int rows,unsigned int cols, double **array);
#endif

void show_matrix(Matrix* m);
void show_float_matrix(Matrix_float* mf);
void show_double_matrix(Matrix_double* md);


void manager_delete_matrix(Matrix *m);
void manager_delete_matrix_float(Matrix_float *mf);
void manager_delete_matrix_double(Matrix_double *md);


void manager_delete_all_matrixs(void);
void destruct_manager(void);



#ifdef __cplusplus
}
#endif




#ifndef HEAP_MEMORY_MANAGEMENT_HELPER_C
#define HEAP_MEMORY_MANAGEMENT_HELPER_C
#include "Heap_memory_management_helper.c"
#endif






#endif